<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>AI搬砖工</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="以足球和NBA球迷的角度讲互联网技术和反心灵鸡汤，顺便聊聊怎么优雅地怼上司。">
<meta name="keywords" content="互联网 大数据 AI 人工智能 机器学习 深度学习 .NET .NETCore Java Spring">
<meta property="og:type" content="website">
<meta property="og:title" content="AI搬砖工">
<meta property="og:url" content="https://keithlibrary.io/index.html">
<meta property="og:site_name" content="AI搬砖工">
<meta property="og:description" content="以足球和NBA球迷的角度讲互联网技术和反心灵鸡汤，顺便聊聊怎么优雅地怼上司。">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="AI搬砖工">
<meta name="twitter:description" content="以足球和NBA球迷的角度讲互联网技术和反心灵鸡汤，顺便聊聊怎么优雅地怼上司。">
  
    <link rel="alternate" href="/atom.xml" title="AI搬砖工" type="application/atom+xml">
  
  
    <link rel="icon" href="https://image.yilingting.com/publics/LOGOs/bzgsoft/favicon.ico">
  
  
    
  
  <link rel="stylesheet" href="/css/style.css">
  

</head>
</html>
<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    
    <div id="header-inner" class="inner">
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="搜索"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://keithlibrary.io"></form>
      </div>
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">首页</a>
        
          <a class="main-nav-link" href="/archives">归档</a>
        
          <a class="main-nav-link" href="/about">关于</a>
        
      </nav>
      
    </div>
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">AI搬砖工</a>
      </h1>
      
        <h2 id="subtitle-wrap">
          <a href="/" id="subtitle">以足球和NBA球迷的角度讲互联网技术和反心灵鸡汤，顺便聊聊怎么优雅地怼上司。</a>
        </h2>
      
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main">
  
    <article id="post-20181005 Azure WebApp Logs自动备份到Azure Storage" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/10/25/20181005 Azure WebApp Logs自动备份到Azure Storage/" class="article-date">
  <time datetime="2018-10-25T03:22:33.000Z" itemprop="datePublished">2018-10-25</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/10/25/20181005 Azure WebApp Logs自动备份到Azure Storage/">Azure WebApp Logs自动备份到Azure Storage</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <!-- Table of Contents -->
        
        <p>Azure WebApp比自己租用IIS部署ASP.NET或者ASP.NET CORE程序有很大的优势，包括但不限于自动缩放（当然是要给钱的）、自动缩放无需配置负载均衡、Visual Studio集成好、部署上传速度快、不需要担心IIS环境部署容易出错等问题。</p>
<p>但有一些用户会觉得不太适应，因为Azure WebApp并非一台虚拟机，可以理解为一个类似于Docker容器，主要是给你程序运行资源，而不是给你用于存储的。Azure WebApp连Web访问日志和系统日志都是需要配置到一个Azure Storage Blob存储里面的，所以它的理念是让存储文件更加“分布式”——就是多个WebApp应该都把日志存放在一个集中的Storage里面。</p>
<p>但是这个给传统程序带来一些不方便，使用log4net、nlog等日志写入组件会需要写入磁盘，而Azure Storage不方便挂载到WebApp里面。如果日志写多了，很可能把Azure WebApp写爆。</p>
<p>那么有两种方法，一种是自定义一个log4net、nlog等的日志Appender，让日志写入到Azure Storage Blob存储或者Table存储里面都可以，这部分代码在GitHub上有一些。配置Appender到log4net.config或者nlog.config就可以使用。</p>
<p>但是笔者在自己试过写一个写入Azure Storage Table的日志记录程序之后，发现大部分情况下Azure Storage Table方案显得有点不方便，有一种更简单的适合更小型程序的方式，就是把log4net或者nlog生成的日志文件归档到Azure Storage Blob里面。</p>
<p>以下就是这个自动备份的程序代码：</p>
<p>Gitee代码Repository：<a href="https://gitee.com/gzkeith/webapp-logs-backup" target="_blank" rel="noopener">https://gitee.com/gzkeith/webapp-logs-backup</a></p>
<p>首先需要建一个WebJob项目，直接在Visual Studio里面建就可以了，但我们如果要定时，则需要加入Microsoft.Azure.WebJobs.Extensions，使用Nuget添加：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E5%8A%A0%E5%85%A52.x%E7%89%88%E6%9C%ACWebJobs_Extensions.png" alt></p>
<p>注意我们使用的是2.x版本，需要保证Azure.WebJobs Nuget包和Extensions Nuget包同版本。现在已经有3.0版本刚刚出来了，写法完全不一样，截止到今天网上找不到多少参考，所以千万别直接升级到3.0或以后。</p>
<p>而目前Visual Studio也没有.net core的WebJob项目模板，暂时还是用.NET Framework 4.6来做吧。</p>
<p>WebJobs项目应该自带WindowsAzure.Storage，这个是使用Storage Blob存储必须的。然后笔者是强迫症升级了最新版本了，再之后，加入一个方便处理的包：Microsoft.Azure.Storage.DataMovement</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E6%B7%BB%E5%8A%A0Microsoft.Azure.Storage.DataMovement%EF%BC%8C%E5%BF%AB%E9%80%9F%E4%BC%A0%E8%BE%93%E6%96%87%E4%BB%B6.png" alt></p>
<p>这个包是微软自己写的，用来高效读写Storage的。用了它，减少处理二进制文件的复杂度。使用里面的TransportManager，直接把文件路径或者Stream传进去，设置一个缓存，UploadAsync就会自动分块多线程上传，不用自己做byte[]缓存了，能够在想要简单解决问题的时候满足我们的需要。</p>
<p>加好了Nuget包，记得在启动前设置UseTimers，不然cron表达式会不起作用：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E8%AE%B0%E5%BE%97UseTimers.png" alt></p>
<p>然后我建立一个定时的WebJobs函数，因为是Debug需要，就设置为2分钟一次，实际上要按照日志文件的分割逻辑、写入空间量设定一个合理的备份时间避免写爆磁盘空间，又不要经常做无必要的轮询：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E4%BD%BF%E7%94%A8Azure%20WebApp%E7%9B%AE%E5%BD%95%EF%BC%8C%E9%9C%80%E8%A6%81%E4%BD%BF%E7%94%A8%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%8E%B7%E5%8F%96WebRoot%E8%B7%AF%E5%BE%84.png" alt></p>
<p>上面这里用了一个环境变量路径：WEBROOT_PATH</p>
<p>这是Azure WebApp自带的，能够直接进到WebApp的运行路径。如果通过GetCurrentDirectory获取执行位置，只会获取到一个临时文件位置，因为WebApp运行会先Copy到一个临时文件位置避免执行时锁死文件路径。</p>
<p>笔者这边使用nlog，直接把文件写到logs目录底下了：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/wwwroot%E6%98%AFWebApp%E7%9A%84%E8%B7%AF%E5%BE%84.png" alt></p>
<p>所以直接组合了DirectoryInfo。</p>
<p>后面就是迭代里面的文件了。笔者直接使用nlog的.net core日志模式，文件名是nlog-all-yyyy-MM-dd.log和nlog-own-yyyy-MM-dd.log这样的格式。于是就扫描里面所有的nlog-*.log，除掉当前（必须使用UTC时间，WebApp上面运行是使用UTC时间的）的日志，其他的日志都归档。</p>
<p>这部分请直接参见代码，就不贴图了。</p>
<p>有一个位置需要注意的，使用DataMovement包的TransferManager.UploadAsync最好配置一下如果遇到文件重名就overwrite，否则会报错：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E6%9C%80%E5%A5%BD%E8%AE%BE%E7%BD%AE%E8%A6%86%E7%9B%96%E6%97%A5%E5%BF%97%EF%BC%8C%E5%90%A6%E5%88%99%E9%81%87%E5%88%B0%E5%90%8C%E5%90%8DCloudBlob%E4%BC%9A%E7%88%86%E5%BC%82%E5%B8%B8.png" alt></p>
<p>接着就是运行问题了。要保证WebJob按时触发不延迟，是需要把WebApp的“始终可用”打开的：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/%E9%9C%80%E8%A6%81%E5%8D%87%E7%BA%A7Azure%20WebApp%E5%88%B0B1%E7%BA%A7%E5%88%AB.png" alt></p>
<p>但是打开这个，显然收费的级别就最少要到B1，费用降不下去了：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20181005/B1%E7%BA%A7%E5%88%AB%E8%B4%B9%E7%94%A8%E6%98%8E%E6%98%BE%E4%B8%8A%E5%8E%BB%E4%BA%86.png" alt></p>
<p>WebApp的App Service Plan上去之后，有10GB存储就没那么容易写爆了，好像意义没那么大了。</p>
<p>其实也是可以在ASP.net程序里面做一个Web API接口，按照存储需要手动触发日志备份，这样就可以经济一点，但就需要做一个自己轮询自己的功能，隔一分钟调用自己一次进行扫描，扫描结束之后再延时调用自己下一次轮询。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://keithlibrary.io/2018/10/25/20181005 Azure WebApp Logs自动备份到Azure Storage/" data-id="ck07sonf70000ugkg1xv6xs0g" class="article-share-link">分享</a>
      
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/NET-Core/">.NET Core</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ASP-NET-Core/">ASP.NET Core</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Azure/">Azure</a></li></ul>

    </footer>
  </div>
  
</article>
 


  
    <article id="post-20180825 ASP.NET Core解决IIS部署2008R2失败与反向代理的问题" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/08/25/20180825 ASP.NET Core解决IIS部署2008R2失败与反向代理的问题/" class="article-date">
  <time datetime="2018-08-25T03:22:33.000Z" itemprop="datePublished">2018-08-25</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/08/25/20180825 ASP.NET Core解决IIS部署2008R2失败与反向代理的问题/">ASP.NET Core + IIS 502.5错误码0x8007010b的解决方法</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <!-- Table of Contents -->
        
        <p>ASP.NET Core是跨平台的Web技术，像Spring Boot一样使用内置Kestrel的方式就能够作为一个进程自己跑起来承担Web应用服务器的功能。</p>
<p>但是Kestrel强项在于处理动态请求，作为Web服务器的能力稍弱，对于静态文件支持、请求缓存等Web服务器功能支持都不算强，并且不建议使用一个控制台进程的方式把Kestrel直接用于生产。</p>
<p>使用Windows平台，通常使用IIS作为Kestrel的反向代理运行起来。使用Linux，我们可以选择使用NginX作为反向代理。</p>
<p>但是在Visual Studio调试中直接使用IIS调试会非常顺利，碰不到实际上线部署所碰到的问题，例如在低版本Windows里面所出现的部署不成功问题。</p>
<p>现在按照开发人员常见的部署IIS步骤，排除一些里面会出现的问题。</p>
<p><strong>一、首先，把一个ASP.NET Core Web程序发布，以下使用默认发布方式</strong>：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/1_%E9%BB%98%E8%AE%A4%E5%8F%91%E5%B8%83%E6%96%B9%E5%BC%8F.png" alt></p>
<p>这是最常见的发布方式。</p>
<p><strong>二、在Win10 IIS里面随便一个站点，创建一个应用程序</strong>：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/2_Win10%E9%BB%98%E8%AE%A4%E9%83%A8%E7%BD%B2.png" alt></p>
<p><strong>三、在确认IIS是否能成功跑起来之前，先用命令行的方式确认直接跑Kestrel能否跑起来</strong>：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/3_%E5%85%88%E7%A1%AE%E8%AE%A4%E7%9B%B4%E6%8E%A5%E8%BF%90%E8%A1%8CKestrel%E8%83%BD%E5%A4%9F%E8%B7%91%E8%B5%B7%E6%9D%A5.png" alt></p>
<p>Ketrel端口默认是5000，建议不要占用它，方便随时使用默认的形式调试。命令行使用</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ dotnet ****.dll</span><br></pre></td></tr></table></figure>

<p>的方式运行，这个是成功的。</p>
<p><strong>四、IIS跑起来的时候报500.19</strong></p>
<p>如图：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/4_%E4%BD%BF%E7%94%A8IIS%E8%BF%90%E8%A1%8C%E6%8A%A5500.19.png" alt></p>
<p>因为我们之前已经确认过Kestrel运行asp.net core站点是正常的，那么到底是什么原因呢？</p>
<p>其实是开发人员在ASP.NET上过于经验丰富，没看说明就跑起来了。</p>
<p>看一下微软的官方指导，如何用IIS Host ASP.NET Core（由于公众号的限制，直接贴网址，网址可能随着版本变，搜索一下就可以了）：</p>
<p><a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-2.1&amp;tabs=aspnetcore2x" target="_blank" rel="noopener">https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-2.1&amp;tabs=aspnetcore2x</a></p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/4.1_%E9%9C%80%E8%A6%81%E7%A1%AE%E4%BF%9D.net%20Core%20Hosting%20Bundle%E5%92%8CC++Redistribution.png" alt></p>
<p>因为ASP.NET Core的运行方式和原来的ASP.NET有所不同，所以不是安装一个.NET Framework就搞定的，需要安装各种组件适配各种情况。.NET Core的Prerequisite就要求C++ 2015 Redistribution，这个在类似于Windows 2008 R2（Win7）这样的老系统上，一般是没有的。而开发人员如果使用Win7来开发，不会出现这个问题，是因为安装Visual Studio的时候会把Microsoft Visual C++ 2015 Redistribution装上，所以本机根本不会有这个问题。</p>
<p>如果没有安装C++ 2015 Redistribution，是会爆“丢失api-ms-win-crt-runtime-l1-1-0.dll”的：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/4.1_%E7%BC%BA%E5%B0%91C++2015Dist.png" alt></p>
<p>.NET Core Hosting Bundle就更加不用说了，用VS调试IIS根本不会报问题，因为VS不是使用web.config文件启动ASP.NET Core程序，是有一套自己的启动方式。</p>
<p><strong>五、安装.NET Core Hosting Bundle</strong></p>
<p>但是我们如果没有安装VS，要单独部署ASP.NET Core的话，需要安装.NET Core Hosting Bundle。网上查的资料通常较旧，都是.NET Core 1.x时代的，那个时代.NET Core Hosting Bundle可能还是单独下载的。而到了ASP.NET Core 2.x，则是通过下载这个：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/5_%E5%AE%89%E8%A3%85.net%20core%20runtime%E4%BD%BF%E7%94%A8IIS%E4%BD%9C%E4%B8%BAASP.NET%20core%E5%AE%BF%E4%B8%BB.png" alt></p>
<p>下载一个.NET Core Runtime，在.NET Core SDK的下载页直接就可以看到了。但笔者真的有点奇怪，为什么Runtime不可以直接包含在SDK里面？SDK应该是基于Runtime提供更多的开发支持，而不是用不同的runtime，所以逻辑上应该是可以合二为一的，至于是不是微软某些技术兼容的考虑就不得而知了。</p>
<p><strong>六：真正的问题来了——运行的时候爆IIS 502.5</strong></p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/6_%E5%86%8D%E6%AC%A1%E8%BF%90%E8%A1%8C%E5%90%8E%E5%8F%98%E6%88%90502.5.png" alt></p>
<p>笔者找这个问题的答案最为费劲，网上什么解答方式都试过，主要都是说安装.NET Core Hosting Bundle就能解决，另外就是看一下Windows日志，看一下报错的问题是什么：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/6.1_ErrorCode_0x8007010b.png" alt></p>
<p>这个问题是从Windows Event Logs里面找到的。错误码0x8007010b。Google一下网上的说法基本上一样，就是安装.NET Core Hosting Bundle，然后针对这条日志记录，看一下web.config文件指示的文件位置是否正确、dotnet命令是否正确等。</p>
<p>实际上我们一开始就已经Kestrel验证过，直接运行“dotnet ***.dll [参数] ”是可行的。那么我们继续排查。</p>
<p><strong>七、尝试解决依赖的部署方式</strong></p>
<p>进程无法启动，意味着不是代码的问题，是IIS运行方式的问题。</p>
<p>我们尝试另一种部署方式：考虑解决所有dll依赖的问题，因为DLL依赖不通过，也是没办法启动起来的，而这通常还无法输出日志。所以我们用SelfContained的发布方式，尽量.NET Runtime启动的时候不报异常：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/7_%E6%8C%89%E7%85%A7SelfContain%E6%96%B9%E5%BC%8F%E5%8F%91%E5%B8%83.png" alt></p>
<p>这个东西是平台相关的，所以如果要跑在Linux等底下就需要另外编译了，有点烦，但是为了先解决问题，暂时不考虑这个。</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/7.1_SelfContained%E7%BC%96%E8%AF%91%E5%87%BA%E5%BE%88%E5%A4%9A%E6%96%87%E4%BB%B61.png" alt></p>
<p>这样会编译出来很多平台相关的、本来该在.net Core SDK里面的DLL。还有一堆的Nuget引用的DLL都被编译生成出来了，跟原来的.NET程序类似，一个小小的ASP.NET Demo项目就会大概100MB左右。</p>
<p>然后我们再部署到没有VS的干净的环境里，这样就可以了么？</p>
<p>Too young, naive呀</p>
<p><strong>八、NuGet安装Microsoft.AspNetCore.Server.IISIntegration，设置UseIISIntegration()</strong></p>
<p>看上面给过的微软官方的IIS Host指导，我们还有一项没有做，就是这个：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/7.2_%E5%AE%89%E8%A3%85IIS%20Integration%20Nuget%E5%92%8CUseIISIntegration().png" alt></p>
<p>ASP.NET Core模板生成的默认代码里面是Program.cs文件的这里：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/7.2.2_%E5%AE%89%E8%A3%85IIS%20Integration%20Nuget%E5%92%8CUseIISIntegration().png" alt></p>
<p>但ASP.NET Core都喜欢使用extensions的方法，到底有没有用，是需要看有没有实现的对象对框架进行依赖注入的。而使用IIS集成的依赖注入，就是在NuGet中安装Microsoft.AspNetCore.Server.IISIntegration。</p>
<p>NuGet如何安装这个的就不在这个文章里面细说了。</p>
<p>这些都做完，在Windows 2008 R2上面重启IIS之后，基本上就OK了。来到这里，其实已经基本上解决了ASP.NET Core + IIS 502.5错误码0x8007010b这个问题。</p>
<p>但是如果IIS Host ASP.NET Core在没有安装VS调试过IIS的Win10上面，事情就还没有完，还是IIS 502.5错误码0x8007010b，What the fuck？</p>
<p><img src="https://image.yilingting.com/publics/common/%E6%88%91%E7%9A%84%E5%86%85%E5%BF%83%E5%87%A0%E4%B9%8E%E6%98%AF%E5%B4%A9%E6%BA%83%E7%9A%84.jpg" alt></p>
<p>后面发现，这个主要的原因，是我们使用服务器跟使用Win10等非服务器系统的不同。</p>
<p><strong>九、设置Windows用户IIS Application Pool对文件访问的权限</strong></p>
<p>通常使用Windows服务器的人都比较懒，直接使用Administrator（或者Administrators用户组，以下不强调了）进行操作，那么很多文件访问的事情都会变得非常方便，因为权限够高。</p>
<p>而通过Administrator登录，安装IIS、创建IIS站点的时候所创建的Application Pool，是继承了拥有足够高的读写权限的。于是Application Pool能够访问除了必须Administrators或者SYSTEM组权限的目录，那么IIS以IIS或者某个IIS Application Pool用户跑Kestrel的时候都能够成功。</p>
<p>而使用Win10等默认给个人使用的操作系统，则可能不会成功，因为我们通常工作在非管理员用户底下，典型的非管理员用户就是使用了Microsoft ID登录Win10，一直没有使用Administrator（从某个时间段开始，微软的操作系统Administrator自动隐藏了，需要net user Administrator /active:yes 才能见到并激活使用）。我们在Win10安装IIS、创建一个新的站点自动创建一个对应的IIS Application Pool用户，其实权限并没有那么高，哪怕安装IIS过程中中间需要弹窗让我们授权。</p>
<p>在Linux底下，需要root权限的命令都需要先sudo，那么补偿的操作，首先不是用Administrator解决所有问题，而是分配一下权限：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/8_%E8%AE%BE%E7%BD%AEIIS%20Application%20Pool%E5%AF%B9%E6%96%87%E4%BB%B6%E8%AE%BF%E9%97%AE%E7%9A%84%E6%9D%83%E9%99%90.png" alt></p>
<p>在你需要运行ASP.NET Core的目录右键-&gt;属性-&gt;安全，通过“编辑……”增加一个你所使用的Application Pool对应的用户的权限来解决。</p>
<p>用户名通常是这种格式：<strong>IIS AppPool&lt;myappoolname&gt;</strong></p>
<p>例如上面的是Wp2Self，在查找用户的时候则输入“IIS AppPool\Wp2Self”查找就出来了。</p>
<p>具体添加的步骤也不细说，估计大部分的读者没太多经验也都有Google的能力。</p>
<p>这次就应该真的解决了。然而这样还没够。既然Windows使用IIS做反向代理到Kestrel这么麻烦，我们试试Linux使用NginX反向代理如何？</p>
<p><strong>十、安装NginX并设置反向代理</strong></p>
<p>安装Nginx也不说了，网上资料非常多，先测试运行一下保证NginX安装成功：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/11_Nginx%E5%9C%A8Linux%E4%B8%8B%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F.png" alt></p>
<p>这次别自作聪明，当个小白，直接看微软的官方指导文档：</p>
<p><a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.1&amp;tabs=aspnetcore2x" target="_blank" rel="noopener">https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-2.1&amp;tabs=aspnetcore2x</a></p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/11.1%E5%A2%9E%E5%8A%A0%E5%8F%8D%E5%93%8D%E4%BB%A3%E7%90%86%E6%8A%8AHttp%20Header%E4%BF%A1%E6%81%AF%E4%BC%A0%E9%80%92%E8%BF%87%E6%9D%A5.png" alt></p>
<p>如果不加这个Http Header Forward，则反向代理就不带信息过来了。</p>
<p>然后在/etc/nginx/conf.d/nginx.conf（没有这个文件就创建一个）配置NginX反向代理：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/12_%E9%85%8D%E7%BD%AENginX%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86.png" alt></p>
<p>来到这里可能需要注意，NginX反向代理并没有像IIS那样还负责把Kestrel跑起来。所以这里的proxy_pass所指向的<a href="http://localhost:5000是需要我们自己通过“dotnet" target="_blank" rel="noopener">http://localhost:5000是需要我们自己通过“dotnet</a> ****.dll”跑起来的。</p>
<p>配置好NginX和跑起Kestrel，sudo nginx -s reload 之后测试一下：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/13_NginX%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E6%88%90%E5%8A%9F.png" alt></p>
<p>我们的服务器的确是变成了NginX了。但是在Linux平台下Kestrel的稳定性，还是需要像SpringBoot直接自己跑Web应用一样，仔细考虑一下稳定性的。</p>
<p><strong>写在最后</strong></p>
<p>其实真的挺累，部署个ASP.NET Core Hello World 都这么困难。除了要解决环境问题，还要解决可靠性问题。</p>
<p>其实如果条件允许，真没必要去花精力在这些上面，直接使用Azure WebApp一键部署：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/20_%E9%80%9A%E8%BF%87Azure%20WebApp%E4%B8%80%E6%AD%A5%E6%90%9E%E5%AE%9A.png" alt></p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/20.1_%E9%80%9A%E8%BF%87Azure%20WebApp%E4%B8%80%E6%AD%A5%E6%90%9E%E5%AE%9A.png" alt></p>
<p>不但不用关心基础设施，一步就部署成功，而且Azure WebApp保证运行在里面的程序很高的可用性，还能自动根据负载缩放程序运行的实例等等功能。</p>
<p>我是不会告诉你这是一个一站式解决的方案的。</p>
<p><img src="https://image.yilingting.com/publics/common/%E6%9C%BA%E6%99%BA.jpg" alt></p>
<p>但是使用Azure WebApp也是有需要注意的地方的。</p>
<p>那就是Azure WebApp未必支持最新的.NET Core，所以需要在控制台里面找Kudu看一下：</p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/20.2_Azure%20WebApp%E8%BD%AC%E5%88%B0Kudu.png" alt></p>
<p><img src="https://image.yilingting.com/publics/blogs/20180825/20.2_Kudu%20Site%20Extensions%E7%9C%8BASP.NET%20Core%E7%89%88%E6%9C%AC.png" alt></p>
<p>部署在Azure WebApp程序的ASP.NET Core的版本，一定要不高于这个版本才行。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://keithlibrary.io/2018/08/25/20180825 ASP.NET Core解决IIS部署2008R2失败与反向代理的问题/" data-id="ck07sonfm0007ugkgqw1z99z1" class="article-share-link">分享</a>
      
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/NET-Core/">.NET Core</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ASP-NET-Core/">ASP.NET Core</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Azure/">Azure</a></li></ul>

    </footer>
  </div>
  
</article>
 


  

</section>
           
    <aside id="sidebar">
  
    
  <div class="widget-wrap">
     
        <h3 class="follow-title ">Follow me</h3>
     
    <div class="widget follow">
      
              <a class="github" aria-hidden="true" href="https://github.com/keith-leung" target="_blank" title="Github"></a>
      
      
      
              <a class="zhihu" aria-hidden="true"  href="https://www.zhihu.com/people/keith-leung-78" target="_blank" title="知乎"></a>
      
      
            <a class="email" aria-hidden="true"  href="mailto:keithlibrary@outlook.com" target="_blank" title="邮箱"></a>
      
    </div>
  </div>


  
    
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title tagcloud">标签云</h3>
    <div class="widget tagcloud">
      <a href="/tags/NET-Core/" style="font-size: 14px;">.NET Core</a> <a href="/tags/ASP-NET-Core/" style="font-size: 14px;">ASP.NET Core</a> <a href="/tags/Azure/" style="font-size: 14px;">Azure</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title recent-posts">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2018/10/25/20181005 Azure WebApp Logs自动备份到Azure Storage/">Azure WebApp Logs自动备份到Azure Storage</a>
          </li>
        
          <li>
            <a href="/2018/08/25/20180825 ASP.NET Core解决IIS部署2008R2失败与反向代理的问题/">ASP.NET Core + IIS 502.5错误码0x8007010b的解决方法</a>
          </li>
        
      </ul>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title archive">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/10/">十月 2018</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/08/">八月 2018</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


  
    
<div class="widget-wrap">
    <h3 class="widget-title">友情链接</h3>
    <div class="widget">
        <ul>
            
            <li>
                <a href="http://blog.giscafer.com">giscafer&#39;s blog</a>
            </li>
            
            <li>
                <a href="http://www.gis520.com">GIS520社区</a>
            </li>
            
        </ul>
    </div>
</div>

  
    <!--微信公众号二维码-->

  <div class="widget-wrap">
    <h3 class="follow-title ">微信公众号</h3>
    <div class="widget wechat-widget">
        <img src="https://image.yilingting.com/publics/LOGOs/bzgsoft/qrcode_for_wechat_aibzg_8cm.jpg" alt="扫码关注" width="250"/>
    </div>
  </div>


  
</aside>

      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-left">
      粤ICP备16108200&nbsp;|&nbsp;
      &copy; 2019 AI搬砖工&nbsp;|&nbsp;
      主题 <a href="https://github.com/giscafer/hexo-theme-cafe/" target="_blank">Cafe</a>
    </div>
    <div id="footer-right">
      联系方式&nbsp;|&nbsp;keithlibrary@outlook.com
    </div>
  </div>
</footer>
 <script src="/jquery/jquery.min.js"></script>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">首页</a>
  
    <a href="/archives" class="mobile-nav-link">归档</a>
  
    <a href="/about" class="mobile-nav-link">关于</a>
  
</nav>
    <img class="back-to-top-btn" src="/images/fly-to-top.png"/>
<script>
// Elevator script included on the page, already.
window.onload = function() {
  var elevator = new Elevator({
    selector:'.back-to-top-btn',
    element: document.querySelector('.back-to-top-btn'),
    duration: 1000 // milliseconds
  });
}
</script>
      

  
    <script>
      var cloudTieConfig = {
        url: document.location.href, 
        sourceId: "",
        productKey: "e2fb4051c49842688ce669e634bc983f",
        target: "cloud-tie-wrapper"
      };
    </script>
    <script src="https://img1.ws.126.net/f2e/tie/yun/sdk/loader.js"></script>
    

  







<!-- author:forvoid begin -->
<!-- author:forvoid begin -->

<!-- author:forvoid end -->

<!-- author:forvoid end -->


  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      })
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      })
    </script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


 <script src="/js/is.js"></script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>
<script src="/js/elevator.js"></script>
  </div>
</body>
</html>